#pragma once
#include "Socket.hpp"
#include <memory>
#include <functional>
#include<sys/wait.h>


using func_t = std::function<void(std::shared_ptr<Socket> ptr,InetAddr client)>;

class TcpServer
{
public:
    TcpServer(uint16_t port,func_t func) : _isrunning(false), _port(port),_func(func)
    {
        _ptr = std::make_unique<TCPSocket>();
        // 封装socket的目的主要是替代我们一直重复的Init接口
        _ptr->BuildTCPSocket(_port);
    }
    ~TcpServer()
    {
    }
    void Run()
    {
        _isrunning = true;
        while (_isrunning)
        {
            InetAddr client;
            auto sock = _ptr->AcceptOrDie(&client);
            if (sock == nullptr)
            {
                // accept失败了，因为内部我们已经处理过了所以这里我们不做过多处理
                continue;
            }
            else
            {
                // 因为要进行长服务，所以这里我们使用多进程
                pid_t id = fork();
                if (id < 0)
                {
                    LOG(LogLevel::ERROR)<<"fork fail!!";
                    exit(1);
                }
                else if(id==0)
                {
                    //子进程：
                    //关闭不需要的描述符：
                    //_ptr->Close();
                    pid_t iid=fork();
                    if(iid==0)
                    {
                        //孙子进程：
                        //负责将从网络中收到的数据发送到上层协议
                        _func(sock,client);
                        sock->Close();
                        exit(0);
                    }
                    else 
                    {
                        //子进程退出
                        std::cout << "子进程退出成功" << std::endl;
                        exit(0);// TCP_server.hpp中

                    }

                }
                else
                {
                    //父进程关闭不需要的描述符并回收子进程：
                    waitpid(id,nullptr,0);
                    LOG(LogLevel::DEBUG)<<"父进程回收成功";
                    sock->Close();
                }
            }
        }
        _isrunning=false;
    }

private:
    bool _isrunning;
    uint16_t _port;
    std::unique_ptr<Socket> _ptr;

    // 要交给上层协议栈的回调函数：
    func_t _func;
};